/**
 * stream.c
 *
 *  Created on: 2019-09-05
 *      Author: chenshisheng
 */

#include "stream/stream.h"

static int _DummyPut(void *stream, unsigned char b)
{
    UNUSED(stream);
    UNUSED(b);

    return 1;
}

static int _DummyGet(void *stream, unsigned char *pb)
{
    UNUSED(stream);
    UNUSED(pb);

    return 0;
}

static void _DummyFlush(void *stream)
{
    UNUSED(stream);
}

int Stream_Init(Stream_t *stream, Stream_Put_t put, Stream_Get_t get, Stream_Flush_t flush, bool useMutex)
{
    int ret = 0;

    stream->put = put ? put : _DummyPut;
    stream->get = get ? get : _DummyGet;
    stream->flush = flush ? flush : _DummyFlush;
#ifdef CMSIS_OS
    if(useMutex)
    {
        osMutexAttr_t attr = {NULL, osMutexRecursive | osMutexPrioInherit, NULL, 0};

        stream->mutexWrite = osMutexNew(&attr);
        stream->mutexRead  = osMutexNew(&attr);
        if(stream->mutexWrite == NULL)
        {
            ret |= 1;
        }

        if(stream->mutexRead == NULL)
        {
            ret |= 2;
        }
    }
    else
    {
        stream->mutexWrite = NULL;
        stream->mutexRead = NULL;
    }
#else
    UNUSED(useMutex);
#endif
    return ret;
}

void Stream_DeInit(Stream_t *stream)
{
    UNUSED(stream);
}

int Stream_Write(void *stream, const void *data, unsigned int size)
{
    int ret;
    unsigned int i;
    const uint8_t *pwd = data;

    Stream_AcquireWrite(stream);
    for(i = 0; i < size; i++)
    {
        ret = Stream_Put(stream, pwd[i]);
        if(ret != 1)
        {
            break;
        }
    }

    Stream_ReleaseWrite(stream);
    return (int)i;
}

int Stream_Read(void *stream, void *data, unsigned int size)
{
    int ret;
    unsigned int i;
    uint8_t *prd = data;

    Stream_AcquireRead(stream);
    for(i = 0; i < size; i++)
    {
        ret = Stream_Get(stream, prd++);
        if(ret != 1)
        {
            break;
        }
    }

    Stream_ReleaseRead(stream);
    return (int)i;
}

int Stream_ReadUntil(void *stream, char buf[], unsigned int maxSize, char till)
{
    unsigned int i;
    int ret;
    char c;
    bool haveLine = FALSE;

    Stream_AcquireRead(stream);
    ret = -1;
    for(i = 0; i < (maxSize - 1); i++)
    {
        if(Stream_Get(stream, (unsigned char *) & c) != 1)
        {
            break;
        }

        if(c == till)
        {
            ret = 0;
            haveLine = TRUE;
            break;
        }

        buf[i] = c;
    }

    buf[i] = '\0';

    // 清除多余的字符
    if((! haveLine) && (i == (maxSize - 1)))
    {
        while(1)
        {
            if(Stream_Get(stream, (unsigned char *) & c) != 1)
            {
                break;
            }

            if(c == till)
            {
                break;
            }
        }
    }

    Stream_ReleaseRead(stream);
    return ret;
}
